package ws.very.util.akka.msg

import akka.actor.ActorLogging
import akka.actor.Actor
import ws.very.util.el.Els._
import ws.very.util.lang.ShortTypes._
import akka.actor.ActorRef
import ws.very.util.lang._
import ws.very.util.akka.actor.ReplyAct
import akka.actor.ActorSystem
import akka.actor.Props

object MsgCenter extends DateCookies {
  case class RegForward(id: S, cond: Cond[A], target: ActorRef, time: L = now.mill)
  case class UnregForward(id: S, timeCond: O[Cond[L]] = None)
  case class Forward(req: Any)
  case class CurRegs()

  val name = "msgCenter"
  def apply(sys: ActorSystem) = sys.actorOf(Props[MsgCenter], name)

}

trait IMsgCenter extends ReplyAct with ActorLogging {
  import MsgCenter._
  val routeMap = scala.collection.mutable.LinkedHashMap[S, (Cond[A], ActorRef, L)]()
  //use2hack
  def baseReceive: Receive = {
    case reg: RegForward =>
      self forward (reg -> true)

    case (reg @ RegForward(id, cond, target, time), needReply: B) =>
      if (rightReg(reg)) {
        add2Route(reg)
        if (needReply) reply(true)
      } else if (needReply) reply(false)

    case Forward(req) =>
      routeMap.toSeq.reverse.find { case (_, (cond, _, _)) => cond(req) }.map {
        case (id, (_, target, _)) =>
          log.debug(s"$req 被id[$id]拦截 目标[$target]")
          target.forward(req)
      }.getOrElse { log.warning(s"$req 没有拦截器") }
    case UnregForward(id, timeCond) =>
      def del = {
        routeMap -= id
        reply(true)
      }
      (routeMap.get(id), timeCond) match {
        case (Some(_), None) => del
        case (Some((_, _, time)), Some(timeCond)) if timeCond(time) => del
        case _ => reply(false)
      }

    case CurRegs =>
      log.info("CurRegs")
      reply(curRegForwards)
    case req => self forward (Forward(req))
  }
  def rightReg(reg: RegForward) = {
    import reg._
    (!routeMap.exists {
      case (rid, (_, _, rTime)) =>
        rid == id && rTime > time
    })
  }

  //use2hack
  def add2Route(reg: RegForward): U = {
    log.info(s"add2Route reg=$reg")
    import reg._
    routeMap += id -> (cond, target, time)
  }

  def curRegForwards = routeMap.map {
    case (id, (cond, target, time)) =>
      RegForward(id, cond, target, time)
  }
}

protected class MsgCenter extends IMsgCenter {
  def receive = baseReceive
}